package com.threadpool;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static testMybatis.BizUtil.stopThreadPool;

/**
 * 线程池的执行过程
 * 设并发任务数为N，对列容量为M
 * 1、当 N <= corePoolSize 时，一旦有新的任务就创建新的线程实例，即使仍然存在闲置的线程
 * 2、当 N > corePoolSize 时，新任务将直接进入一个阻塞队列
 * 3、当 N >= corePoolSize + M 时(即队列已满)，将再次开始创建新的线程实例，来处理新的任务
 * 4、当 N > maximumPoolSize 时，采用拒绝处理任务的策略。默认是抛出异常，jdk至少提供4中拒绝任务的策略
 * <p>
 * 线程池中几个重要的参数
 * 1、corePoolSize - 核心线程数，默认一直存在于线程池中的线程数
 * 2、maximumPoolSize - 最大线程数
 * 3、keepAliveTime - 除核心线程外，其他闲置线程可以存活的最大时间
 * 4、unit - 时间单位
 * 5、workQueue - 工作对列
 * 6、threadFactory - 线程工厂，默认是DefaultThreadFactory
 * 7、handler - 拒绝执行处理器
 * 准确理解这几个参数可以自定义线程池的参数
 * <p>
 * 几种线程池
 * newSingleThreadPool：
 * 使用无界队列LinkedBlockQueue，corePoolSize == maximumPoolSize == 1，可以保证池中的任务顺序执行。
 * newFixedThreadPool：
 * 使用无界对列LinkedBlockQueue，不会出现队列满的情况，故不会出现拒绝处理任务的情况，jvm允许会一直任务会一直加入队列
 * newCachedThreadPool：
 * 使用同步队列SynchronousQueue，队列用作生产者和消费者通信的桥梁，若生产者发现没有等待的消费者，
 * 在没有任务处理的情况下，会自动关闭
 * newScheduleThreadPool：
 * 周期性的执行特定任务
 * <p>
 * <p>
 * Created by houjinxin on 16/9/3.
 */
public class ThreadPoolClient {

    private static final CountDownLatch COUNT = new CountDownLatch(20);

    public static void main(String[] args) throws InterruptedException {

//        ExecutorService service = Executors.newFixedThreadPool(10);
        ExecutorService service = Executors.newCachedThreadPool();
//        ExecutorService service = Executors.newSingleThreadExecutor();
//        ExecutorService service = Executors.newScheduledThreadPool(10);
        for (int i = 1; i <= 20; i++) {
//            if (i == 17) {
//                service.shutdown();
//            }
            ThreadPoolExecutor executor = (ThreadPoolExecutor) service;
            System.out.println("任务" + i + "提交前，线程池大小：" + executor.getPoolSize()+"，workQueue："+ executor.getQueue().size());
//            System.out.println("任务" + i + "提交");
            service.execute(new QueryDBTask(i, COUNT));

        }
        COUNT.await(1, TimeUnit.SECONDS);

        stopThreadPool(service);
    }



}
